package server;

import datastorage.DataStorage;
import datastorage.sql.SqlDataStorage;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import server.session.UserSession;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Yuri Denison
 * @since 04.08.11
 */
public class Server {
    private Communicator communicator;
    private DataStorage dataStorage;
    private ServerSocket serverSocket;
    private Map<Integer, UserSession> createdSessions;

    private Thread worker = null;
    private volatile boolean stopped = false;
    private int lastSessionId = 0;
    private static final int DEFAULT_SERVER_PORT = 2222;
    private static final int MAX_SESSION_NUMBER = 100;

    private Logger log = Logger.getLogger(Server.class);

    public Server(int port, DataStorage dataStorage) throws IOException {
        serverSocket = new ServerSocket(port);
        this.dataStorage = dataStorage;
        this.communicator = new Communicator();
        this.createdSessions = new HashMap<Integer, UserSession>();
    }

    public Server(DataStorage dataStorage) throws IOException {
        this(DEFAULT_SERVER_PORT, dataStorage);
    }


    public void start() {
        if (worker != null) {
            stop();
        }
        log.debug("Staring new thread...");
        worker = new Thread(new Runnable() {
            @Override
            public void run() {
                while (lastSessionId < MAX_SESSION_NUMBER && !stopped) {
                    try {
                        Socket socket = serverSocket.accept();
                        log.debug("Log: [server] new connection: [" + socket + "]");
                        Connector connector = new Connector(socket);

                        UserSession session = new UserSession(lastSessionId, connector, dataStorage, communicator);
                        createdSessions.put(lastSessionId, session);
                        lastSessionId++;
                    } catch (IOException e) {
                        log.error("Error init socket!");
                    }
                }
            }
        });

        worker.start();
    }

    public void stop() {
        if (worker != null) {
            log.debug("Stopping thread...");
            for (UserSession userSession : createdSessions.values()) {
                userSession.stop();
            }
            stopped = true;
            worker = null;
        }
    }

    public static void main(String[] args) throws IOException {
        PropertyConfigurator.configure("Server/res/log4j.properties");
        Server server = new Server(new SqlDataStorage());
        server.start();
    }
}
